package com.jz.banner.screen.ui

import android.annotation.SuppressLint
import android.app.Activity
import android.app.Application
import android.content.Context
import android.content.pm.ApplicationInfo
import android.database.sqlite.SQLiteDatabase
import androidx.multidex.MultiDex
import com.alibaba.android.arouter.launcher.ARouter
import com.danikula.videocache.HttpProxyCacheServer
import com.jz.banner.screen.banner.utils.ActivityUtils
import com.jz.banner.screen.bean.database.DaoMaster
import com.jz.banner.screen.bean.database.DaoSession
import com.jz.banner.screen.bean.database.MySqlLiteOpenHelper
import com.jz.banner.screen.listener.MyActivityLifecycleCallbacks
import com.jz.banner.screen.net.MyHttpLoggingInterceptor
import com.jz.banner.screen.services.AppService
import com.jz.banner.screen.utils.ApkHelper
import com.jz.banner.screen.utils.CommUtils
import com.jz.banner.screen.utils.Params
import com.jz.banner.screen.utils.SPUtils
import com.lzy.okgo.OkGo
import com.lzy.okgo.cache.CacheEntity
import com.lzy.okgo.cache.CacheMode
import com.lzy.okgo.https.HttpsUtils
import okhttp3.OkHttpClient
import org.greenrobot.greendao.query.QueryBuilder
import java.io.File
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import java.util.logging.Level
import javax.net.ssl.HttpsURLConnection
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager


/**
 * 创建者     Noel
 * 创建时间   2017/12/20 11:21
 */
class App : Application() {

    override fun onCreate() {
        super.onCreate()
        registerActivityLifecycleCallbacks(object : MyActivityLifecycleCallbacks() {
            override fun onActivityResumed(activity: Activity) {
                ActivityUtils.mCurrentRunActivity = activity.packageName.plus(".").plus(activity.localClassName)
                d("mCurrentRunActivity:${ActivityUtils.mCurrentRunActivity}")
            }
        })
        context = this
        handleSSLHandshake()
        isDebug = isApkDebug(this)

        MultiDex.install(this)
        initOkGo()

        //初始化屏幕的宽高，密度
        var dm = context!!.resources.displayMetrics
        screenWidth = dm.widthPixels
        screenHeight = dm.heightPixels
        density = dm.density
        initARouter()
        initGreenDao()
        initAppService()
        mShopScreenType = SPUtils.getInt(Params.merchant_screen_type, 6)
    }

    private fun initARouter() {
        //是否进行ARouter调试(可以通过AppConfig.isDebug=true/false来判断日志的是否开启)
        if (App.isDebug) {
            //下面两句话必须放到init前面,否则配置无效
            ARouter.openLog();  //打印ARouter日志
            ARouter.openDebug();  //开启ARouter的调试模式(如果在InstantRun模式下运行,必须开启调试模式,线上版本需要关闭，否则有安全风险),
        }
        //官方建议在Application里面进行初始化(使用该注解路径至少两级)
        ARouter.init(this);
    }

    private fun initGreenDao() {
        //获取可写数据库
        mHelper = MySqlLiteOpenHelper(this, "SahBanner.db", null)//建库

        //获取数据库对象
        mSQLiteDatabase = mHelper?.writableDatabase
        mDaoMaster = DaoMaster(mSQLiteDatabase)
        mDaoSession = mDaoMaster?.newSession()

        QueryBuilder.LOG_SQL = isDebug;
        QueryBuilder.LOG_VALUES = isDebug;
    }

    private fun initAppService() {
        try {
            AppService.startAppService(this)
        } catch (e: Exception) {
            d("initAppService：失败-> ${e}")
        }
    }

    fun d(msg: String) {
        CommUtils.println("Application->", msg)
    }

    private fun initOkGo() {
        val builder = OkHttpClient.Builder()
        if (isDebug) {
            val loggingInterceptor = MyHttpLoggingInterceptor("OkGo")
            loggingInterceptor.setPrintLevel(MyHttpLoggingInterceptor.Level.BODY)        //log打印级别，决定了log显示的详细程度
            loggingInterceptor.setColorLevel(Level.INFO)                               //log颜色级别，决定了log在控制台显示的颜色
            builder.addInterceptor(loggingInterceptor)                                //添加OkGo默认debug日志
        }
        //方法一：信任所有证书,不安全有风险
        //方法一：信任所有证书,不安全有风险
        val sslParams1 = HttpsUtils.getSslSocketFactory()
        builder.sslSocketFactory(sslParams1.sSLSocketFactory, sslParams1.trustManager)
        //超时时间设置，默认60秒
        builder.readTimeout(30000L, TimeUnit.MILLISECONDS);     //全局的读取超时时间
        builder.writeTimeout(30000L, TimeUnit.MILLISECONDS)     //全局的写入超时时间
        builder.connectTimeout(30000L, TimeUnit.MILLISECONDS)  //全局的连接超时时间


        // 其他统一的配置
        // 详细说明看GitHub文档：https://github.com/jeasonlzy/
        OkGo.getInstance()
            .init(this)                           //必须调用初始化
            .setOkHttpClient(builder.build())               //建议设置OkHttpClient，不设置会使用默认的
            //.addCommonHeaders(Params.getHeads())
            //.retryCount = 3                                 //全局统一超时重连次数，默认为三次，那么最差的情况会请求4次(一次原始请求，三次重连请求)，不需要可以设置为0
            .setCacheMode(CacheMode.REQUEST_FAILED_READ_CACHE)
            .setRetryCount(0)
            .setCacheTime(CacheEntity.CACHE_NEVER_EXPIRE)
        //.setCacheMode(CacheMode.NO_CACHE)               //全局统一缓存模式，默认不使用缓存，可以不传
        // .setCacheTime(CacheEntity.CACHE_NEVER_EXPIRE)   //全局统一缓存时间，默认永不过期，可以不传


    }

    companion object {
        var MRollingTime: Float = 3f

        @SuppressLint("StaticFieldLeak")
        var context: Context? = null
        var flag = -1 //用来标志 是否 被系统干掉了然后重启app

        //var updateTimes = 0 //更新次数
        fun instance() = context!!

        var isDebug: Boolean = false
        var mIsShowIp: Boolean = false
        var screenWidth: Int = 0
        var screenHeight: Int = 0
        var density: Float = 0f
        var mMaxNumRoll: Int = 6
        var mRequestUpdateTime: Int = 3600

        var mDaoSession: DaoSession? = null
        var mSQLiteDatabase: SQLiteDatabase? = null
        var mDaoMaster: DaoMaster? = null
        var mHelper: MySqlLiteOpenHelper? = null
        var mShopScreenType: Int = 6 //商户显示屏样式
        var mDnsIp: String = "223.5.5.5" //223.6.6.6    114.114.114.114

        //判断是是否debug模式
        fun isApkDebug(context: Context): Boolean {
            return try {
                val info = context.applicationInfo
                info.flags and ApplicationInfo.FLAG_DEBUGGABLE != 0
            } catch (e: Exception) {
                false
            }/*true*/
        }

        fun handleSSLHandshake() {
            try {
                val trustAllCerts: Array<TrustManager> = arrayOf<TrustManager>(object : X509TrustManager {
                    override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {
                    }

                    override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {
                    }

                    override fun getAcceptedIssuers(): Array<X509Certificate?>? = arrayOfNulls(0)

                })
                val sc: SSLContext = SSLContext.getInstance("TLS")
                // trustAllCerts信任所有的证书
                sc.init(null, trustAllCerts, SecureRandom())
                HttpsURLConnection.setDefaultSSLSocketFactory(sc.socketFactory)
                HttpsURLConnection.setDefaultHostnameVerifier { hostname, session -> true }
            } catch (ignored: java.lang.Exception) {
            }
        }

        fun getProxy(context: Context): HttpProxyCacheServer? {
            val app: App = context.applicationContext as App
            return if (app.proxy == null) app.newProxy().also { app.proxy = it } else app.proxy
        }
    }

    private var proxy: HttpProxyCacheServer? = null
    private fun newProxy(): HttpProxyCacheServer? {
        val downloadApkCachePath = ApkHelper.getDownloadApkCachePath().plus("/video_files/")
        val file = File(downloadApkCachePath)
        if (!file.exists()) file.mkdirs()
        return HttpProxyCacheServer.Builder(this)
            //.cacheDirectory(File(downloadApkCachePath))
            .maxCacheFilesCount(10)
            .maxCacheSize(1024 * 1024 * 1024)     // 1 Gb for cache
            .build();
    }

}